using System;
using SharpPieces.Web.Controls;
using System.Collections.Generic;
using System.Web;
using System.Web.UI.WebControls;
using System.Security.Permissions;


namespace SharpPieces.DemoApp.LiveGrid
{

    /// <summary>
    /// LiveGrid Data Provider customization.
    /// </summary>
    [AspNetHostingPermission(SecurityAction.LinkDemand, Level = AspNetHostingPermissionLevel.Minimal), AspNetHostingPermission(SecurityAction.InheritanceDemand, Level = AspNetHostingPermissionLevel.Minimal)]
    public class ActionsDataProvider : LiveGridDataProvider
    {

        // Methods

        /// <summary>
        /// Initializes a new instance of the <see cref="ActionsDataProvider"/> class.
        /// </summary>
        public ActionsDataProvider()
        {
            // subscribe to command click event
            this.CommandClick += new CommandEventHandler(ActionsDataProvider_CommandClick);
        }

        /// <summary>
        /// Handles the CommandClick event of the ActionsDataProvider control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">
        /// The <see cref="System.Web.UI.WebControls.CommandEventArgs"/> 
        /// instance containing the event data.</param>
        protected void ActionsDataProvider_CommandClick(object sender, CommandEventArgs e)
        {
            // handle the command request
            switch (e.CommandName)
            {
                case "delete":
                    int id;
                    if ((null != e.CommandArgument) && 
                        int.TryParse(e.CommandArgument.ToString(), out id))
                    {
                        this.HandleDelete(id);
                    }
                    break;
            }
        }

        private void HandleDelete(int id)
        {
            List<DesignTimeSourceObj> designData = this.AllData;
            DesignTimeSourceObj designTimeObj = designData.Find(
                delegate(DesignTimeSourceObj dto)
                {
                    return id == dto.SomeInt;
                }
            );
            if (null != designTimeObj)
            {
                designData.Remove(designTimeObj);
            }
        }

        /// <summary>
        /// Occurs when a grid needs a data source.
        /// </summary>
        /// <param name="offset">The row offset.</param>
        /// <param name="pageSize">The size of the page.</param>
        /// <param name="totalCount">The total count.</param>
        /// <returns>An IList, IEnumerable or IListSource.</returns>
        public override object NeedDataSource(int offset, int pageSize, 
            out int totalCount)
        {
            return this.NeedDataSource(offset, pageSize, out totalCount, 
                null, SortDirection.Ascending);
        }

        /// <summary>
        /// Occurs when a grid needs a data source.
        /// </summary>
        /// <param name="offset">The row offset.</param>
        /// <param name="pageSize">The size of the page.</param>
        /// <param name="totalCount">The total count.</param>
        /// <param name="sortExpression">The sort expression.</param>
        /// <param name="sortDirection">The sort direction.</param>
        /// <returns>An IList, IEnumerable or IListSource.</returns>
        public override object NeedDataSource(int offset, int pageSize, out int totalCount, 
            string sortExpression, SortDirection sortDirection)
        {
            List<DesignTimeSourceObj> designData = this.AllData;

            // sort the objects based on the received args
            designData.Sort(delegate(DesignTimeSourceObj x, DesignTimeSourceObj y)
                {
                    if ((null == x as object) || (null == y as object))
                    {
                        throw new InvalidOperationException("Cannot compare null values.");
                    }

                    if (sortExpression == "SomeInt")
                    {
                        return (sortDirection == SortDirection.Ascending ? 1 : -1) * 
                            x.SomeInt.CompareTo(y.SomeInt);
                    }
                    else if (sortExpression == "SomeString1")
                    {
                        if ((null == x.SomeString1) || (null == y.SomeString1))
                        {
                            throw new InvalidOperationException("Cannot compare null values.");
                        }
                        return (sortDirection == SortDirection.Ascending ? 1 : -1) *
                            x.SomeString1.CompareTo(y.SomeString1);
                    }
                    else if (sortExpression == "SomeString2")
                    {
                        if ((null == x.SomeString2) || (null == y.SomeString2))
                        {
                            throw new InvalidOperationException("Cannot compare null values.");
                        }
                        return (sortDirection == SortDirection.Ascending ? 1 : -1) * 
                            x.SomeString2.CompareTo(y.SomeString2);
                    }
                    else if (sortExpression == "SomeDateTime")
                    {
                        return (sortDirection == SortDirection.Ascending ? 1 : -1) * 
                            x.SomeDateTime.CompareTo(y.SomeDateTime);
                    }
                    throw new ArgumentException("?");
                });

            totalCount = designData.Count;
            DesignTimeSourceObj[] page = 
                new DesignTimeSourceObj[Math.Min(pageSize, designData.Count - offset)];
            designData.CopyTo(offset, page, 0, page.Length);
            return new List<DesignTimeSourceObj>(page);
        }


        // Properties

        /// <summary>
        /// Gets not persistent runtime generated data.
        /// </summary>
        /// <value>Not persistent runtime generated data.</value>
        private List<DesignTimeSourceObj> AllData
        {
            get
            {
                if (HttpContext.Current.Session["DesignData"] == null)
                {
                    HttpContext.Current.Session["DesignData"] = DesignTimeSourceObj.Generate(45551);
                }
                return (List<DesignTimeSourceObj>)HttpContext.Current.Session["DesignData"];
            }
        }

    }

    /// <summary>
    /// Test object.
    /// </summary>
    public class DesignTimeSourceObj
    {

        // Fields

        int someInt;
        string someString1;
        string someString2;
        DateTime someDateTime;


        // Methods

        /// <summary>
        /// Initializes a new instance of the <see cref="DesignTimeSourceObj"/> class.
        /// </summary>
        public DesignTimeSourceObj()
        {
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="DesignTimeSourceObj"/> class.
        /// </summary>
        /// <param name="someInt">Some int.</param>
        /// <param name="someString1">Some string1.</param>
        /// <param name="someString2">Some string2.</param>
        /// <param name="someDateTime">Some date time.</param>
        public DesignTimeSourceObj(int someInt, string someString1, string someString2, 
            DateTime someDateTime)
        {
            this.someInt = someInt;
            this.someString1 = someString1;
            this.someString2 = someString2;
            this.someDateTime = someDateTime;
        }
        

        // Properties

        /// <summary>
        /// Gets or sets some int.
        /// </summary>
        /// <value>Some int.</value>
        public int SomeInt
        {
            get { return someInt; }
            set { someInt = value; }
        }

        /// <summary>
        /// Gets or sets some string1.
        /// </summary>
        /// <value>Some string1.</value>
        public string SomeString1
        {
            get { return someString1; }
            set { someString1 = value; }
        }

        /// <summary>
        /// Gets or sets some string2.
        /// </summary>
        /// <value>Some string2.</value>
        public string SomeString2
        {
            get { return someString2; }
            set { someString2 = value; }
        }

        /// <summary>
        /// Gets or sets some date time.
        /// </summary>
        /// <value>Some date time.</value>
        public DateTime SomeDateTime
        {
            get { return someDateTime; }
            set { someDateTime = value; }
        }

        /// <summary>
        /// Generates a list of test objects.
        /// </summary>
        /// <param name="no">The no of test objects to generate.</param>
        /// <returns></returns>
        public static List<DesignTimeSourceObj> Generate(int no)
        {
            List<DesignTimeSourceObj> res = new List<DesignTimeSourceObj>();
            for (int i = 0; i < no; i++)
            {
                res.Add(new DesignTimeSourceObj(i, "some" + i.ToString(), "other" + i.ToString(), 
                    DateTime.Now.AddDays(i)));
            }
            return res;
        }

    }

}
